package com.spark.common.utils;

import com.spark.common.exception.SparkException;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 反射工具类
 *
 * @author LYCHEE
 * @date 2025/2/18 13:30
 */
public class ReflectUtils {

    /**
     * 递归查找字段
     *
     * @param clazz     class
     * @param fieldName 字段名
     * @return
     */
    public static Field findField(Class<?> clazz, String fieldName) {
        return findField(clazz, fieldName, true);
    }

    /**
     * 递归查找字段，不一定在本类中
     *
     * @param clazz       class
     * @param fieldName   字段名
     * @param isRecursion 是否递归查找父类
     * @return 返回字段信息
     */
    public static Field findField(Class<?> clazz, String fieldName, boolean isRecursion) {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            if (isRecursion) {
                Class<?> superclass = clazz.getSuperclass();
                if (superclass != null) {
                    return findField(superclass, fieldName, isRecursion);
                }
            }
        }
        return null;
    }


    /**
     * 利用反射获取实体类中的某个字段的值-递归
     *
     * @param entity    实体
     * @param strField  字段
     * @param fieldType 返回值类型
     * @return 字段的值
     */
    public static <T, R> R getField(T entity, String strField, Class<R> fieldType) {
        return getField(entity, strField, true, fieldType);
    }

    /**
     * 利用反射获取实体类中的某个字段的值
     *
     * @param entity      实体
     * @param strField    字段
     * @param isRecursion 是否递归查找需要的字段
     * @param fieldType   返回值类型
     * @return 字段的值
     */
    public static <T, R> R getField(T entity, String strField, boolean isRecursion, Class<R> fieldType) {
        Field field = findField(entity.getClass(), strField, isRecursion);
        if (null == field) {
            throw new SparkException("Could not find field");
        }
        try {
            field.setAccessible(true);
            Object value = field.get(entity);
            // 将 Object 类型转换为指定类型
            return fieldType.cast(value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 利用反射设置实体类中的某个字段的值-递归
     *
     * @param entity   实体
     * @param strField 字段名称
     * @param value    要设置的值
     */
    public static <T> void setField(T entity, String strField, Object value) {
        setField(entity, strField, value, true);
    }

    /**
     * 利用反射设置实体类中的某个字段的值
     *
     * @param entity      实体
     * @param strField    字段名称
     * @param isRecursion 是否递归查找需要设置的字段
     * @param value       要设置的值
     */
    public static <T> void setField(T entity, String strField, Object value, boolean isRecursion) {
        Field field = findField(entity.getClass(), strField, isRecursion);
        if (null == field) {
            throw new SparkException("Could not find field");
        }
        try {
            field.setAccessible(true);
            field.set(entity, value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取类的所有属性，包括父类
     *
     * @param object
     * @return
     */
    public static Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

}
